use std::assert;
use std::ptr;
use std::sync::atomic::{AtomicUsize, Ordering};
macro_rules! assert {
    ($ expr : expr) => {
        num_assert.fetch_add(1, Ordering::SeqCst);
        if !$expr {
            panic!("Assertion failed: {}", stringify!($expr));
        }
    };
}
static mut num_assert: AtomicUsize = AtomicUsize::new(0);
type UnitTestFunction = fn();
type ArrayListValue = *mut std::ffi::c_void;
#[repr(C)]
struct ArrayList {
    data: *mut ArrayListValue,
    length: u32,
    _alloced: u32,
}
type ArrayListEqualFunc = fn(ArrayListValue, ArrayListValue) -> i32;
type ArrayListCompareFunc = fn(ArrayListValue, ArrayListValue) -> i32;
static mut variable1: i32 = 0;
static mut variable2: i32 = 0;
static mut variable3: i32 = 0;
static mut variable4: i32 = 0;
static tests: &[UnitTestFunction] = &[
    test_arraylist_new_free,
    test_arraylist_append,
    test_arraylist_prepend,
    test_arraylist_insert,
    test_arraylist_remove,
    test_arraylist_remove_range,
    test_arraylist_index_of,
    test_arraylist_clear,
    test_arraylist_sort,
];
#[allow(dead_code)]
fn generate_arraylist() -> *mut ArrayList {
    let arraylist: *mut ArrayList;
    let i: i32;
    unsafe {
        arraylist_new = arraylist_new_new(0);
        for i in 0..4 {
            arraylist_append(arraylist, &variable1 as *const _ as *mut _);
            arraylist_append(arraylist, &variable2 as *const _ as *mut _);
            arraylist_append(arraylist, &variable3 as *const _ as *mut _);
            arraylist_append(arraylist, &variable4 as *const _ as *mut _);
        }
    }
    return arraylist_new;
}
#[test]
fn test_arraylist_new_free() {
    let mut arraylist: *mut ArrayList;
    arraylist_new = arraylist_new_new(0);
    assert!(!arraylist.is_null());
    arraylist_free(arraylist);
    arraylist_new = arraylist_new_new(10);
    assert!(!arraylist.is_null());
    arraylist_free(arraylist);
    arraylist_free(ptr::null_mut());
    alloc_test_set_limit(0);
    arraylist_new = arraylist_new_new(0);
    assert!(arraylist.is_null());
    alloc_test_set_limit(1);
    arraylist_new = arraylist_new_new(100);
    assert!(arraylist.is_null());
}
#[test]
fn test_arraylist_append() {
    let mut variable1 = 1;
    let mut variable2 = 2;
    let mut variable3 = 3;
    let mut variable4 = 4;
    let arraylist = arraylist_new(0);
    assert!((*arraylist).length == 0);
    assert!(arraylist_append(arraylist, &mut variable1 as *mut i32) != 0);
    assert!((*arraylist).length == 1);
    assert!(arraylist_append(arraylist, &mut variable2 as *mut i32) != 0);
    assert!((*arraylist).length == 2);
    assert!(arraylist_append(arraylist, &mut variable3 as *mut i32) != 0);
    assert!((*arraylist).length == 3);
    assert!(arraylist_append(arraylist, &mut variable4 as *mut i32) != 0);
    assert!((*arraylist).length == 4);
    assert!(*(*(*arraylist).data.offset(0)) == variable1);
    assert!(*(*(*arraylist).data.offset(1)) == variable2);
    assert!(*(*(*arraylist).data.offset(2)) == variable3);
    assert!(*(*(*arraylist).data.offset(3)) == variable4);
    for _ in 0..10000 {
        assert!(arraylist_append(arraylist, ptr::null_mut()) != 0);
    }
    arraylist_free(arraylist);
    let arraylist = arraylist_new(100);
    alloc_test_set_limit(0);
    for _ in 0..100 {
        assert!(arraylist_append(arraylist, ptr::null_mut()) != 0);
    }
    assert!((*arraylist).length == 100);
    assert!(arraylist_append(arraylist, ptr::null_mut()) == 0);
    assert!((*arraylist).length == 100);
    arraylist_free(arraylist);
}
#[test]
fn test_arraylist_prepend() {
    unsafe {
        let mut arraylist = ArrayList::new(0);
        assert!((*arraylist).length == 0);
        assert!((*arraylist).prepend(&mut variable1) != 0);
        assert!((*arraylist).length == 1);
        assert!((*arraylist).prepend(&mut variable2) != 0);
        assert!((*arraylist).length == 2);
        assert!((*arraylist).prepend(&mut variable3) != 0);
        assert!((*arraylist).length == 3);
        assert!((*arraylist).prepend(&mut variable4) != 0);
        assert!((*arraylist).length == 4);
        assert!((*arraylist).data.offset(0) == &mut variable4 as *mut _);
        assert!((*arraylist).data.offset(1) == &mut variable3 as *mut _);
        assert!((*arraylist).data.offset(2) == &mut variable2 as *mut _);
        assert!((*arraylist).data.offset(3) == &mut variable1 as *mut _);
        for _ in 0..10000 {
            assert!((*arraylist).prepend(ptr::null_mut()) != 0);
        }
        ArrayList::free(arraylist);
        arraylist = ArrayList::new(100);
        alloc_test_set_limit(0);
        for _ in 0..100 {
            assert!((*arraylist).prepend(ptr::null_mut()) != 0);
        }
        assert!((*arraylist).length == 100);
        assert!((*arraylist).prepend(ptr::null_mut()) == 0);
        assert!((*arraylist).length == 100);
        ArrayList::free(arraylist);
    }
}
#[test]
fn test_arraylist_insert() {
    let mut arraylist = generate_arraylist();
    let variable1 = 1;
    let variable2 = 2;
    let variable3 = 3;
    let variable4 = 4;
    assert!(arraylist.length == 16);
    assert!(arraylist_insert(&mut arraylist, 17, &variable1) == 0);
    assert!(arraylist.length == 16);
    assert!(arraylist.length == 16);
    assert!(arraylist.data[4] == &variable1);
    assert!(arraylist.data[5] == &variable2);
    assert!(arraylist.data[6] == &variable3);
    assert!(arraylist_insert(&mut arraylist, 5, &variable4) != 0);
    assert!(arraylist.length == 17);
    assert!(arraylist.data[4] == &variable1);
    assert!(arraylist.data[5] == &variable4);
    assert!(arraylist.data[6] == &variable2);
    assert!(arraylist.data[7] == &variable3);
    assert!(arraylist.data[0] == &variable1);
    assert!(arraylist.data[1] == &variable2);
    assert!(arraylist.data[2] == &variable3);
    assert!(arraylist_insert(&mut arraylist, 0, &variable4) != 0);
    assert!(arraylist.length == 18);
    assert!(arraylist.data[0] == &variable4);
    assert!(arraylist.data[1] == &variable1);
    assert!(arraylist.data[2] == &variable2);
    assert!(arraylist.data[3] == &variable3);
    assert!(arraylist.data[15] == &variable2);
    assert!(arraylist.data[16] == &variable3);
    assert!(arraylist.data[17] == &variable4);
    assert!(arraylist_insert(&mut arraylist, 18, &variable1) != 0);
    assert!(arraylist.length == 19);
    assert!(arraylist.data[15] == &variable2);
    assert!(arraylist.data[16] == &variable3);
    assert!(arraylist.data[17] == &variable4);
    assert!(arraylist.data[18] == &variable1);
    for _i in 0..10000 {
        arraylist_insert(&mut arraylist, 10, &variable1);
    }
    arraylist_free(arraylist);
}
#[no_mangle]
#[no_mangle]
#[no_mangle]
#[test]
fn test_arraylist_remove_range() {
    INIT.call_once(|| unsafe {
        variable0 = libc::malloc(std::mem::size_of::<u32>()) as *mut _;
        variable1 = libc::malloc(std::mem::size_of::<u32>()) as *mut _;
    });
    let arraylist = unsafe { generate_arraylist() };
    unsafe {
        assert!((*arraylist).length == 16);
        assert!((*arraylist).data[3] == &variable4 as *const _ as *mut _);
        assert!((*arraylist).data[4] == &variable1 as *const _ as *mut _);
        assert!((*arraylist).data[5] == &variable2 as *const _ as *mut _);
        assert!((*arraylist).data[6] == &variable3 as *const _ as *mut _);
    }
    unsafe {
        arraylist_remove_range(arraylist, 4, 3);
    }
    unsafe {
        assert!((*arraylist).length == 13);
        assert!((*arraylist).data[3] == &variable4 as *const _ as *mut _);
        assert!((*arraylist).data[4] == &variable4 as *const _ as *mut _);
        assert!((*arraylist).data[5] == &variable1 as *const _ as *mut _);
        assert!((*arraylist).data[6] == &variable2 as *const _ as *mut _);
    }
    unsafe {
        arraylist_remove_range(arraylist, 10, 10);
        arraylist_remove_range(arraylist, 0, 16);
    }
    unsafe {
        assert!((*arraylist).length == 13);
        arraylist_free(arraylist);
    }
}
#[test]
fn test_arraylist_remove() {
    use std::ptr;
    let mut arraylist = generate_arraylist();
    assert_eq!(arraylist.length, 16);
    assert!(ptr::eq(arraylist.data[3], &variable4));
    assert!(ptr::eq(arraylist.data[4], &variable1));
    assert!(ptr::eq(arraylist.data[5], &variable2));
    assert!(ptr::eq(arraylist.data[6], &variable3));
    arraylist_remove(&mut arraylist, 4);
    assert_eq!(arraylist.length, 15);
    assert!(ptr::eq(arraylist.data[3], &variable4));
    assert!(ptr::eq(arraylist.data[4], &variable2));
    assert!(ptr::eq(arraylist.data[5], &variable3));
    assert!(ptr::eq(arraylist.data[6], &variable4));
    arraylist_remove(&mut arraylist, 15);
    assert_eq!(arraylist.length, 15);
    arraylist_free(arraylist);
}
#[test]
fn test_arraylist_index_of() {
    let entries = [89, 4, 23, 42, 16, 15, 8, 99, 50, 30];
    let num_entries;
    let mut arraylist: ArrayList;
    let mut val;
    num_entries = entries.len();
    arraylist = arraylist_new(0);
    for i in 0..num_entries {
        let entry_ptr = &entries[i] as *const i32 as *mut i32;
        arraylist_append(&mut arraylist, entry_ptr);
    }
    for i in 0..num_entries {
        val = entries[i];
        let index = arraylist_index_of(&arraylist, int_equal, &val);
        assert!(index == i as i32);
    }
    val = 0;
    assert!(arraylist_index_of(&arraylist, int_equal, &val) < 0);
    val = 57;
    assert!(arraylist_index_of(&arraylist, int_equal, &val) < 0);
    unsafe {
        arraylist_free(arraylist);
    }
}
#[test]
fn test_arraylist_clear() {
    let variable1 = Box::new(1);
    let variable2 = Box::new(2);
    let variable3 = Box::new(3);
    let variable4 = Box::new(4);
    let mut arraylist = arraylist_new(0);
    arraylist_clear(&mut arraylist);
    assert_eq!(arraylist.length, 0);
    arraylist_append(&mut arraylist, variable1);
    arraylist_append(&mut arraylist, variable2);
    arraylist_append(&mut arraylist, variable3);
    arraylist_append(&mut arraylist, variable4);
    arraylist_clear(&mut arraylist);
    assert_eq!(arraylist.length, 0);
    arraylist_free(arraylist);
}
#[test]
fn test_arraylist_sort() {
    let entries = vec![89, 4, 23, 42, 4, 16, 15, 4, 8, 99, 50, 30, 4];
    let sorted = vec![4, 4, 4, 4, 8, 15, 16, 23, 30, 42, 50, 89, 99];
    let num_entries = entries.len();
    let mut arraylist = arraylist_new(10);
    for i in 0..num_entries {
        arraylist_prepend(&mut arraylist, &entries[i]);
    }
    arraylist_sort(&mut arraylist, int_compare);
    assert!(arraylist.length == num_entries);
    for i in 0..num_entries {
        let value: &i32 = arraylist.data[i];
        assert!(*value == sorted[i]);
    }
    arraylist_free(arraylist);
    let mut arraylist = arraylist_new(5);
    arraylist_sort(&mut arraylist, int_compare);
    assert!(arraylist.length == 0);
    arraylist_free(arraylist);
    let mut arraylist = arraylist_new(5);
    arraylist_prepend(&mut arraylist, &entries[0]);
    arraylist_sort(&mut arraylist, int_compare);
    assert!(arraylist.length == 1);
    assert!(arraylist.data[0] == &entries[0]);
    arraylist_free(arraylist);
}
fn main() {
    run_tests(tests);
    println!("num_assert: {}", num_assert);
}
